Release 10.1A: OpenEdge Development:
Programming Interfaces


Implementing symmetric cryptography in the 4GL

Once you have established an appropriate cryptography policy for your application, including the necessary key values and algorithms, you can begin to apply encryption and decryption to your data. However, you must also thoroughly plan the role that cryptography plays in your application in order to use it safely and effectively. While the 4GL provides powerful tools for generating keys and encrypting data, you must manage these tools carefully in your application to avoid serous problems that could result in loss of data.

Caution: Before encrypting any data that you intend to have decrypted, be certain that you can recover the unencrypted data if either the encryption or decryption fails.

For more information, in general, on managing data encryption and decryption, see the Security whitepaper prepared by Progress Marketing, which can be found on the PSDN Web site.

Using the 4GL encryption and decryption functions

The Progress 4GL provides two 4GL built-in functions, DECRYPT and ENCRYPT, to encrypt and decrypt data. Both functions rely on cryptographic parameters that you set using the SECURITY-POLICY system handle or using options for invoking each function.

These functions have the following syntax:

Syntax
ENCRYPT ( data-to-encrypt [ , encrypt-key [ , iv-value [ , algorithm ] ] ] ) 

DECRYPT ( data-to-decrypt [ , encrypt-key [ , iv-value [ , algorithm ] ] ] ) 

You can provide the data-to-encrypt as a CHARACTER, LONGCHAR, RAW, or MEMPTR variable, and the ENCRYPT function evaluates to a MEMPTR value containing the encrypted binary byte stream of the data. You can provide the data-to-decrypt as a MEMPTR or RAW variable containing an encrypted binary byte stream, and the DECRYPT function evaluates to a MEMPTR value containing the decrypted binary byte stream of the data. You can then convert the decrypted MEMPTR value to a CHARACTER or LONGCHAR in order to make the decrypted data human-readable. If you need to encrypt and decrypt more than one value, you can marshall these items to and unmarshall them from a MEMPTR using PUT-datatype statements and GET-datatype functions.

If you specify a parameter value for any of the function options, it overrides any setting of the corresponding SECURITY-POLICY handle attribute. In order to successful decrypt an encrypted value (resulting in a DECRYPT return value identical to the data-to-encrypt value that you input to ENCRYPT), you must invoke both functions using identical cryptographic parameters as shown in Table 2–14, whether you supply them as function options or as attributes of your application cryptography policy.

Table 2–14: ENCRYPT/DECRYPT function parameters
Set this cryptographic parameter using...
This function
option...
Or this SECURITY-POLICY
handle attribute...
Symmetric key
encrypt-key 
SYMMETRIC-ENCRYPTION-KEY 
Initialization vector
iv-value 
SYMMETRIC-ENCRYPTION-IV 
Algorithm, mode, and key size
algorithm 
SYMMETRIC-ENCRYPTION-ALGORITHM 

For many applications, you do not need to specify an initialization vector and can use the default algorithm, mode, and key size ("AES_CBC_128"). Typically, you only need to set these values to satisfy specific application requirements.

You must handle all generation, storage, transportation, and provision of the symmetric key and all other values required to decrypt data that you have encrypted. This includes maintaining binary keys in the correct byte endian order for the platform or platforms where cryptographic operations occur.

For information on:

The following section describes some code examples using the 4GL cryptographic functions.

Example code using the ENCRYPT and DECRYPT functions

This section shows basic uses of the 4GL symmetric cryptography functions and related 4GL elements.

Example 2–1 shows the use of a random binary key to encrypt the text "Bathtub Pancake Ladybug".

DEFINE VARIABLE binary-key AS RAW. 
DEFINE VARIABLE clear-text AS CHARACTER INIT "Bathtub Pancake Ladybug". 
DEFINE VARIABLE crypto-value AS RAW. 
binary-key = GENERATE-RANDOM-KEY. 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = binary-key. 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?. 
crypto-value = Encrypt (clear-text). 

Example 2–1: Encryption using a random binary key

For the receiver of the crypto-value to be able to successfully decrypt the value and recover the clear text requires the following information:

  1. The name of the algorithm (the default, "AES_CBC_128", used and obtained by reading SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM).
  2. The initialization vector (none used, but available by reading SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV).
  3. The binary key value.
  4. Note: Setting SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY directly from the GENERATE-RANDOM-KEY function leads to an irrecoverable key because this attribute is write-only and GENERATE-RANDOM-KEY returns a different value if called again.

Example 2–2 shows the use of a binary key to decrypt the text from the previous example.

DEFINE VARIABLE binary-key AS RAW. 
DEFINE VARIABLE clear-text AS CHARACTER. 
DEFINE VARIABLE crypto-value AS RAW. 
/* binary-key is set to the same value as in the previous example */ 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = binary-key. 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?. 
/* crypto-value is obtained by some means */ 
clear-text = DECRYPT (crypto-value). 

Example 2–2: Decryption using a random binary key

Example 2–3 shows the use of a password-based key to encrypt the text, "Matter Property Mass Solid". The password is "Migratory Blueberries".

DEFINE OUTPUT PARAMETER salt-value AS RAW. 
DEFINE VARIABLE password AS CHARACTER INIT "Migratory Blueberries". 
DEFINE VARIABLE clear-text AS CHARACTER INIT "Matter Property Mass Solid". 
DEFINE VARIABLE crypto-value AS RAW. 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM = "AES_CBC_256". 
SECURITY-POLICY:PBE-KEY-ROUNDS = 2000. 
SECURITY-POLICY:PBE-HASH-ALGORITHM = "MD5". 
SECURITY-POLICY:ENCRYPTION-SALT = GENERATE-PBE-SALT. 
/* The salt value is passed as an OUTPUT parameter for use by the 
 * following password decryption example */ 
salt-value = SECURITY-POLICY:ENCRYPTION-SALT. 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = GENERATE-PBE-KEY (password). 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?. 
crypto-value = ENCRYPT (clear-text). 

Example 2–3: Encryption using a password-based key

For the receiver of the crypto-value to be able to successfully decrypt the value and recover the clear text, the following information is necessary:

  1. The name of the algorithm (a non-default value specified and obtained by reading SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM).
  2. The initialization vector (none is used, but can be set using SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV).
  3. The number of hashing algorithm iterations to generate the key (a non-default value specified and obtained by reading SECURITY-POLICY:PBE-KEY-ROUNDS).
  4. The salt value (obtained by reading SECURITY-POLICY:ENCRYPTION-SALT).
  5. Note: Calling GENERATE-PBE-SALT function again produces a different salt value and is not useful in generating the binary key necessary to decrypt the text.

  6. The hash algorithm used to transform the password into the binary key (a non-default value specified and obtained by reading SECURITY-POLICY:PBE-HASH-ALGORITHM).
  7. The password text.

In place of items 3 through 6, the binary key value itself can be supplied. Because SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY is write-only, an intermediate RAW variable can be used to hold the value returned from the GENERATE-PBE-KEY function, or the function may be called again with the same password value (it will return the same result provided the SECURITY-POLICY system handle attributes SYMMETRIC-ENCRYPTION-ALGORITHM, PBE-KEY-ROUNDS, PBE-HASH-ALGORITHM, and ENCRYPTION-SALT all have the same values).

Example 2–4 shows the use of a password-based key to decrypt the text from the previous example. The password is "Migratory Blueberries".

/* The salt value from the previous password encryption example is 
 * passed in as an INPUT parameter */ 
DEFINE INPUT PARAMETER salt-value AS RAW. 
/* The password is most likely obtained from the user and not 
 * in the code as shown here. */ 
DEFINE VARIABLE password AS CHARACTER INIT "Migratory Blueberries". 
DEFINE VARIABLE clear-text AS CHARACTER. 
DEFINE VARIABLE crypto-value AS RAW. 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM = "AES_CBC_256". 
SECURITY-POLICY:PBE-KEY-ROUNDS = 2000. 
SECURITY-POLICY:PBE-HASH-ALGORITHM "MD5". 
SECURITY-POLICY:ENCRYPTION-SALT = salt-value. 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = GENERATE-PBE-KEY (password). 
SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?. 
/* crypto-value is obtained by some means */ 
clear-text = DECRYPT (crypto-value). 

Example 2–4: Decryption using a password-based key

Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095